namespace Be
{
	template<typename T>
	std::map<Entity*, T*> ComPtr<T>::m_ComponentMap;

	template<typename T>
	ComPtr<T>::ComPtr()
		: m_pData(0)
	{
	}

	template<typename T>
	ComPtr<T>::ComPtr(T* p_pData)
		: m_pData(p_pData)
	{
		if(m_pData)
		{
			++m_pData->m_RefCount;
		}
	}

	template<typename T>
	ComPtr<T>::ComPtr(const ComPtr<T>& p_pData)
		: m_pData(p_pData.m_pData)
	{
		if(m_pData)
		{
			++m_pData->m_RefCount;
		}
	}

	template<typename T>
	ComPtr<T>::~ComPtr()
	{
		if(m_pData)
		{
			assert(m_pData->m_RefCount > 0);

			--m_pData->m_RefCount;

			if(m_pData->m_RefCount == 0)
			{
				m_ComponentMap.erase(m_pData->m_pEntity);
				delete m_pData;
			}
		}
	}

	template<typename T>
	void ComPtr<T>::Initialize(Entity* p_pEntity)
	{
		assert(p_pEntity != 0);
		assert(m_pData == 0);

		std::map<Entity*, T*>::iterator l_Iter = m_ComponentMap.find(p_pEntity);
		if(l_Iter != m_ComponentMap.end())
		{
			m_pData = l_Iter->second;
		}
		else
		{
			m_pData = new T(p_pEntity);
			m_ComponentMap[p_pEntity] = m_pData;
		}

		++m_pData->m_RefCount;
	}

	template<typename T>
	ComPtr<T>& ComPtr<T>::operator=(T* p_pData)
	{
		if(m_pData)
		{
			assert(m_pData->m_RefCount > 0);

			--m_pData->m_RefCount;

			if(m_pData->m_RefCount == 0)
			{
				m_ComponentMap.erase(m_pData->m_pEntity);
				delete m_pData;
			}
		}

		m_pData = p_pData;

		if(m_pData)
		{
			++m_pData->m_RefCount;
		}

		return *this;
	}

	template<typename T>
	ComPtr<T>& ComPtr<T>::operator=(const ComPtr<T>& p_pData)
	{
		if(m_pData)
		{
			assert(m_pData->m_RefCount > 0);

			--m_pData->m_RefCount;

			if(m_pData->m_RefCount == 0)
			{
				m_ComponentMap.erase(m_pData->m_pEntity);
				delete m_pData;
			}
		}

		m_pData = p_pData.m_pData;

		if(m_pData)
		{
			++m_pData->m_RefCount;
		}

		return *this;
	}

	template<typename T>
	bool ComPtr<T>::operator==(const T* p_pData) const
	{
		return m_pData == p_pData;
	}

	template<typename T>
	bool ComPtr<T>::operator==(const ComPtr<T>& p_pData) const
	{
		return m_pData == p_pData.m_pData;
	}

	template<typename T>
	bool ComPtr<T>::operator!=(const T* p_pData) const
	{
		return m_pData != p_pData;
	}

	template<typename T>
	bool ComPtr<T>::operator!=(const ComPtr<T>& p_pData) const
	{
		return m_pData != p_pData.m_pData;
	}

	template<typename T>
	bool ComPtr<T>::operator<(const ComPtr<T>& p_pData) const
	{
		return m_pData < p_pData.m_pData;
	}

	template<typename T>
	T* ComPtr<T>::operator->()
	{
		return m_pData;
	}
}